package com.king.wxpay.util;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.security.KeyStore;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 微信支付工具类
 * @author taomk
 * @version 1.0
 * @since 15-7-10 下午4:08
 */
public class WxUtil {

	public static final ConcurrentHashMap<String, String> OUT_TRAD_NO_CACHE = new ConcurrentHashMap<String, String>();

	public static final String PARAM_APPID = "appid";

	public static final String PARTNER_ID = "partnerid";

	public static final String PREPAY_ID = "prepayid";

	public static final String PAPAM_TIMESTAMP = "timestamp";

	public static final String PARAM_NONCESTR = "noncestr";

	public static final String PARAM_SINGTYPE = "signType";

	public static final String PARAMS_PACKAGE = "package";

	public static final String PARAMS_PAYSIGN = "paySign";

	public static String map2sign(Map<String, String> map, String keys)
			throws Exception {

		String buff = "";
		try {
			List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
					map.entrySet());

			Collections.sort(infoIds,
					new Comparator<Map.Entry<String, String>>() {
						public int compare(Map.Entry<String, String> o1,
										   Map.Entry<String, String> o2) {
							return (o1.getKey()).toString().compareTo(
									o2.getKey());
						}
					});

			for (int i = 0; i < infoIds.size(); i++) {
				Map.Entry<String, String> item = infoIds.get(i);
				// System.out.println(item.getKey());
				if (item.getValue() != "") {

					String key = item.getKey();
					String val = item.getValue();
					buff += key + "=" + val + "&";

				}
			}
			// buf.append("key=" + key);
			if (keys != null && !"".equals(keys)) {
				buff += "key=" + keys;
			} else {
				if (buff.isEmpty() == false) {
					buff = buff.substring(0, buff.length() - 1);
				}
			}
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
		return EncryptUtil.MD5(buff).toUpperCase();
	}

	public static String genAppSign(List<Pair<String, String>> params) {
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < params.size(); i++) {
			sb.append(params.get(i).getKey());
			sb.append('=');
			sb.append(params.get(i).getValue());
			sb.append('&');
		}
		sb.append("key=");
		sb.append(WxConfig.API_SECRET);
		return EncryptUtil.MD5(sb.toString()).toUpperCase().toUpperCase();
	}

//	public static String map2sign(Map<String, String> map) throws Exception {
//
//		String buff = "";
//		try {
//			List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(
//					map.entrySet());
//
//			Collections.sort(infoIds,
//					new Comparator<Map.Entry<String, String>>() {
//						public int compare(Map.Entry<String, String> o1,
//										   Map.Entry<String, String> o2) {
//							return (o1.getKey()).toString().compareTo(
//									o2.getKey());
//						}
//					});
//
//			for (int i = 0; i < infoIds.size(); i++) {
//				Map.Entry<String, String> item = infoIds.get(i);
//				// System.out.println(item.getKey());
//				if (item.getValue() != "") {
//
//					String key = item.getKey();
//					String val = item.getValue();
//					buff += key + "=" + val + "&";
//
//				}
//			}
//			// buf.append("key=" + key);
//			System.out.println("1111111111111111");
//			buff += "key=" + WxConfig.API_SECRET;
//			/*
//			 * if (buff.isEmpty() == false) { buff = buff.substring(0,
//			 * buff.length() - 1); }
//			 */
//		} catch (Exception e) {
//			throw new Exception(e.getMessage());
//		}
//		System.out.println(buff.toString());
//		return EncryptUtil.MD5(buff).toUpperCase();
//
//	}

	public static String createSign(Object bean, String key) {
		try {
			StringBuilder buf = new StringBuilder();
			PropertyDescriptor[] pds = BeanUtil.getPropDescs(bean.getClass());
			TreeMap<String, Object> map = new TreeMap<String, Object>();
			for (PropertyDescriptor pd : pds) {
				String name = pd.getName();
				if ("class".equals(name))
					continue;
				if ("key".equals(name))
					continue;
				if ("sign".equals(name))
					continue;
				Object value = pd.getReadMethod().invoke(bean);
				if (value == null)
					continue;
				map.put(name, value);
			}

			Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry<String, Object> entry = it.next();
				Object k = entry.getKey();
				Object v = entry.getValue();
				buf.append(k);
				buf.append("=");
				buf.append(v);
				buf.append("&");
			}
			buf.append("key=" + key);

			String sign = EncryptUtil.MD5(buf.toString()).toUpperCase();
			return sign;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

    /*
	public static String createSign(Object bean) {
        try {
            StringBuilder buf = new StringBuilder();
            PropertyDescriptor[] pds = BeanUtil.getPropDescs(bean.getClass());
            TreeMap<String, Object> map = new TreeMap<String, Object>();
            for (PropertyDescriptor pd : pds) {
                String name = pd.getName();
                if ("class".equals(name))
                    continue;
                if("key".equals(name))
                    continue;
                Object value = pd.getReadMethod().invoke(bean);
                if (value == null)
                    continue;
                map.put(name, value);
            }

            Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator();
            while (it.hasNext()) {
                Map.Entry<String, Object> entry = it.next();
                Object k = entry.getKey();
                Object v = entry.getValue();
                buf.append(k);
                buf.append("=");
                buf.append(v);
                buf.append("&");
            }
            buf.append("key=" + mchKey);
            logger.info(buf.toString());

            String sign = EncryptUtil.MD5(buf.toString()).toUpperCase();
            return sign;
        } catch (Exception e) {
            logger.warning(e.toString());
        }
        return null;
    }
*/

	private static String chars = "0123456789abcdefghigklmnopqrstuvwxyz";

	/**
	 * @return
	 * @description 生成随机数的方法
	 */
	public static String getRandomStr() {
		char[] array = new char[32];
		Random random = new Random();
		for (int i = 0; i < 32; i++) {
			int c = random.nextInt(36);
			array[i] = chars.charAt(c);
		}
		return new String(array);
	}

	public static void main(String[] args) {
		System.out.println(getRandomStr());
	}

	public static String postSSLXml(String url, String xml) throws Exception {
		String text = null;
		StringBuilder sb = new StringBuilder();
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
		FileInputStream instream = new FileInputStream(new File(WxConfig.PFILE_PATH));
		try {
			keyStore.load(instream, WxConfig.MCH_ID.toCharArray());
		} finally {
			instream.close();
		}

		// Trust own CA and all self-signed certs
		SSLContext sslcontext = SSLContexts
				.custom()
				.loadKeyMaterial(keyStore, WxConfig.MCH_ID.toCharArray()).build();
		// Allow TLSv1 protocol only
		SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
				sslcontext, new String[]{"TLSv1"}, null,
				SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
		CloseableHttpClient httpclient = HttpClients.custom()
				.setSSLSocketFactory(sslsf).build();
		try {

			HttpPost http = new HttpPost(url);
			StringEntity payload = new StringEntity(xml, "UTF-8");
			http.setEntity(payload);
			System.out.println("executing request" + http.getRequestLine());

			CloseableHttpResponse response = httpclient.execute(http);
			try {
				HttpEntity entity = response.getEntity();

				if (entity != null) {

					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(entity.getContent()));
					while ((text = bufferedReader.readLine()) != null) {
						sb.append(text);
					}

				}
				EntityUtils.consume(entity);
			} finally {
				response.close();
			}
		} finally {
			httpclient.close();
		}

		return sb.toString();
	}

	public static String postXml(String url, String xml) throws Exception {
		String text = null;
		StringBuilder sb = new StringBuilder();
		HttpPost httpPost = new HttpPost(url);
		HttpEntity entity = null;

		httpPost.setHeader(HTTP.CONTENT_TYPE,
				"application/x-www-form-urlencoded");
		try {

			HttpClient client = new DefaultHttpClient();
			StringEntity payload = new StringEntity(xml, "UTF-8");
			httpPost.setEntity(payload);
			HttpResponse response = client.execute(httpPost);
			entity = response.getEntity();

			if (entity != null) {

				BufferedReader bufferedReader = new BufferedReader(
						new InputStreamReader(entity.getContent()));
				while ((text = bufferedReader.readLine()) != null) {
					// System.out.println(text);
					sb.append(text);
				}

			}
		} catch (Exception e) {
			System.out.println("与[" + url + "]通信过程中发生异常,堆栈信息如下");
			e.printStackTrace();
		} finally {
			try {
				EntityUtils.consume(entity);
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return sb.toString();
	}


//	private static ConcurrentHashMap<String, KeyManager[]> keyManagerMap = new ConcurrentHashMap<String, KeyManager[]>();
//	private static ConcurrentHashMap<String, TrustManager[]> trustManagerMap = new ConcurrentHashMap<String, TrustManager[]>();
//
//
//	public static KeyManager[] getKeyManagers(String appid) {
//		KeyManager[] keyManagers = keyManagerMap.get(appid);
//		if (keyManagers == null) {
//			keyManagers = KeyTool.getKeyManagers(WxConfig.MCH_ID, WxConfig.PFILE_PATH, "PKCS12");
//			keyManagerMap.put(appid, keyManagers);
//		}
//		return keyManagers;
//	}
//
//	public static TrustManager[] getTrustManagers(String appid) {
//		TrustManager[] trustManagers = trustManagerMap.get(appid);
//		if (trustManagers == null) {
//			trustManagers = KeyTool.getTrustManagers(WxConfig.MCH_ID, WxConfig.PFILE_PATH, "JKS");
//			trustManagerMap.put(appid, trustManagers);
//		}
//		return trustManagers;
//	}
//
//	public static byte[] doPost(String appid, String url, byte[] content) {
//		try {
//			SimpleHttp http = new SimpleHttp(url);
//			HttpURLConnection con = http.getConnection();
//			con.setRequestMethod("POST");
//			con.setDoInput(true);
//			con.setDoOutput(true);
//			con.setConnectTimeout(3000);
//			String protocol = http.getURL().getProtocol();
//			if ("https".equals(protocol)) {
//				http.setSSLContext(WxUtil.getKeyManagers(appid),
//						WxUtil.getTrustManagers(appid));
//				http.setHostnameVerifier(new SimpleHttp.DefaultHostnameVerifier());
//			}
//			http.connect();
//			http.writeBytes(content);
//			// String result=http.readString("UTF-8");
//			byte[] retBytes = http.readBytes();
//			return retBytes;
//		} catch (Exception e) {
//			e.printStackTrace();
//			return null;
//		}
//	}
//
//	public static SimpleHttp doConnect(String appid, String url) {
//		try {
//			SimpleHttp http = new SimpleHttp(url);
//			HttpURLConnection con = http.getConnection();
//			con.setRequestMethod("POST");
//			con.setDoInput(true);
//			con.setDoOutput(true);
//			con.setConnectTimeout(3000);
//			String protocol = http.getURL().getProtocol();
//			if ("https".equals(protocol)) {
//				http.setSSLContext(WxUtil.getKeyManagers(appid), WxUtil.getTrustManagers(appid));
//				http.setHostnameVerifier(new SimpleHttp.DefaultHostnameVerifier());
//			}
//			http.connect();
//			return http;
//		} catch (Exception e) {
//			e.printStackTrace();
//			return null;
//		}
//	}

	public static String buildResultXml(String returnCode, String returnMsg) {
//		PrePayRes ret = new PrePayRes();
//		ret.setReturn_code(returnCode);
//		ret.setReturn_msg(returnMsg);
//		return new String(SimpleXml.marshall(ret));
		return null;
	}
}
